#pragma once
#include "../comm/comm.hpp"
#include "../comm/log.hpp"

using namespace Ns_Comm;
// 编号，标题，难度，时间复杂度，空间复杂度，题目描述，用户代码块，测试用例代码块
struct Question
{
    std::string _number;
    std::string _title;
    std::string _star; // 简单 中等 困难
    int _cpu_limit;
    int _mem_limit;
    std::string _desc;
    std::string _header;
    std::string _tail;
};

const std::string loadpath = "./questions/";
const std::string host = "127.0.0.1";
const std::string user = "oj";
const std::string passwd = "zsw203526";
const std::string dbname = "online_oj";
const int port = 3306;

const std::string sql = "select * from question;";

class Model
{
private:

    void exec(const std::vector<std::string>& row)
    {
        assert(row.size() == 8);
        Question q;
        q._number = row[0];
        q._title = row[1];
        q._star = row[2];
        q._cpu_limit = std::stoi(row[3]);
        q._mem_limit = std::stoi(row[4]);
        q._desc = row[5];
        q._header = row[6];
        q._tail = row[7];
        _questions[q._number] = q;
    }

    bool LoadQuestions()
    {
        if(!_sql_handler->excuteSQL(sql, std::bind(&Model::exec, this, std::placeholders::_1)))
        {
            LOG(LogInfo, "加载题目列表失败\n");
            return false;
        }

        LOG(LogInfo, "加载题目列表成功\n");
        return true;
    }

    // bool LoadQuestions(const std::string &load_path)
    // {
    //     std::string questions_list_path = PathTool::SplicingQuestionsList(load_path);
    //     std::ifstream in(questions_list_path);
    //     if (!in.is_open())
    //     {
    //         LOG(LogError, "%s中第%d行打开文件发生错误: %s\n", __FILE__, __LINE__, questions_list_path.c_str());
    //         return false;
    //     }
    //     // FileTool::FileRead(questions_list_path, &question_list);

    //     std::string line;
    //     while (getline(in, line))
    //     {
    //         std::vector<std::string> v;
    //         StringTool::Spilit(line, &v, " ");
    //         if (v.size() != 5)
    //         {
    //             LOG(LogWarning, "%s中第%d行，题目加载错误\n", __FILE__, __LINE__);
    //             continue;
    //         }

    //         Question q;
    //         q._number = v[0];
    //         q._title = v[1];
    //         q._star = v[2];
    //         q._cpu_limit = std::stoi(v[3]);
    //         q._mem_limit = std::stoi(v[4]);

    //         std::string desc_path = PathTool::SplicingQuestionDesc(q._number, load_path);
    //         FileTool::FileRead(desc_path, &q._desc, true);

    //         std::string header_path = PathTool::SplicingQuestionHeader(q._number, load_path);
    //         FileTool::FileRead(header_path, &q._header, true);

    //         std::string tail_path = PathTool::SplicingQuestionTail(q._number, load_path);
    //         FileTool::FileRead(tail_path, &q._tail, true);

    //         _questions.insert({q._number, q});
    //     }

    //     // LOG(LogInfo, "加载题目列表成功\n");
    //     return true;
    // }

public:
    Model()
        : _sql_handler(std::make_unique<MySQLHelpper>())
    {
        assert(_sql_handler->connect(host, user, passwd, dbname, port));
        assert(LoadQuestions());
        // assert(LoadQuestions(loadpath));
    }

    bool GetAllQuestion(std::vector<Question> *out)
    {
        if (_questions.size() == 0)
        {
            LOG(LogWarning, "题目列表为空\n");
            return false;
        }

        for (auto &e : _questions)
        {
            out->push_back(e.second);
        }

        // LOG(LogInfo, "获取题目列表成功\n");
        sort(out->begin(), out->end(), [](Question&q1, Question& q2)
        {
            return std::stoi(q1._number) < std::stoi(q2._number);
        });
        return true;
    }

    bool GetNumQuestion(const std::string &number, Question *q)
    {
        auto iter = _questions.find(number);
        if (iter == _questions.end())
        {
            LOG(LogFatal, "没有对应的题目: %s\n", number.c_str());
            return false;
        }

        *q = iter->second;
        // LOG(LogInfo, "获取题目成功: %s\n", number.c_str());
        return true;
    }

    ~Model() {}

private:
    unordered_map<std::string, Question> _questions;
    std::unique_ptr<MySQLHelpper> _sql_handler;
};